<?php

if (! defined('LIB_PATH'))
{
    die('The file ' . __FILE__ . ' needs to be required from the main executable of PhpPhoenix');
}

/**
 * This class is inheriting the Base class
 *
 * @see Base
 */
require_once LIB_PATH . 'Base.php';

/**
 * PhpElement 
 * 
 * @package php-phoenix
 * @subpackage models
 * @version $id$
 * @copyright 
 * @author Pablo López Torres <pablolopeztorres@gmail.com> 
 * @license 
 */
abstract class PhpElement extends Base
{
    /**
     * container 
     * 
     * @var PhpElement
     * @access private
     */
    private $container = NULL;

    /**
     * sourcecode 
     * 
     * @var PhpElement
     * @access private
     */
    private $sourcecode = NULL;

	private $identifier;

    /**
     * __construct
     * 
     * @param string|NULL $container 
     * @author Pablo López Torres <pablo@redcore.es> 
     * @access public
     */
    public function __construct($identifier, PhpElement $container = NULL)
    {
		if (! is_string($identifier)) throw new Exception();

		$this->identifier = $identifier;
        $this->container = $container;
    }

	/**
	 * setName
	 * 
	 * @access public
	 * @author Pablo López Torres <pablolopeztorres@gmail.com> 
	 * @param mixed $identifier 
	 * @return void
	 */
	public function setName($identifier)
	{
		$this->identifier = $identifier;
	}
	
	/**
	 * getName
	 * 
	 * @access public
	 * @author Pablo López Torres <pablolopeztorres@gmail.com> 
	 * @return void
	 */
	public function getName()
	{
		return $this->identifier;
	}
	
	/**
	 * getIdentifier
	 * 
	 * @access public
	 * @author Pablo López Torres <pablolopeztorres@gmail.com> 
	 * @return void
	 */
	public function getIdentifier()
	{
		return $this->identifier;
	}

    /**
     * getFile
     * 
     * @author Pablo López Torres <pablolopeztorres@gmail.com>
     * @access public
     * @return PhpElement
     */
    public function getFile()
    {
		$container = $this->container;
		while (! $container instanceof PhpFile)
		{
			$container = $container->getContainer();
		}
        return $this->container;
    }

    /**
     * getFilename
     * 
     * @author Pablo López Torres <pablolopeztorres@gmail.com>
     * @access public
     * @return PhpElement
     */
    public function getFilename()
    {
        return $this->getFile()->getIdentifier();
    }


	public function getContainer()
	{
		return $this->container;
	}

	public function setContainer(PhpElement $container)
	{
		$this->container = $container;
	}


	/**
	 * setSourceTokens
	 * 
	 * @author Pablo López Torres <pablolopeztorres@gmail.com> 
	 * @param array $sourcecode Array of tokens
	 * @return void
	 */
	public function setSourceTokens(array $sourceTokens)
	{
		$this->sourcecode = $sourceTokens;
	}

	/**
	 * getSourceTokens
	 * 
	 * @author Pablo López Torres <pablolopeztorres@gmail.com> 
	 * @return array
	 */
	public function getSourceTokens()
	{
		if ($this->sourcecode === NULL)
		{
			throw new UnableToRetrieveSourcecodeException();
		}

		return $this->sourcecode;
	}

	/**
	 * getSourcecode
	 * 
	 * @access public
	 * @author Pablo López Torres <pablolopeztorres@gmail.com> 
	 * @param boolean $formatted (default: FALSE)
	 * @param integer $indentation (default: 0)
	 * @return string
	 */
	public function getSourcecode($formatted = FALSE, $indentation = 0)
	{
		$source = '';
		foreach ($this->getSourceTokens() as $token)
		{
			$source .= $token[1];
		}
		return $source;
	}


	/**
	 * getProject
	 * 
	 * @access private
	 * @author Pablo López Torres <pablolopeztorres@gmail.com> 
	 * @return Project
	 */
	public function getProject()
	{
		$container = $this->getContainer();
		while (! $container instanceof Project)
		{
			$container = $container->getContainer();

			if ($container === NULL)
			{
				throw new ProjectNotSetForClassException();
			}
		}
	}


	/**
	 * save
	 * 
	 * @access public
	 * @author Pablo López Torres <pablolopeztorres@gmail.com> 
	 * @return boolean Success
	 */
	public function save()
	{
		// save contents
		foreach ($this->elements as $element)
		{
			$element->save();
		}
		// save itself
		return Storage::save($this, $this->getPersistentKey(), TRUE);
	}


	/**
	 * Gets an unique identifier for the element.
	 * 
	 * @author Pablo López Torres <pablolopeztorres@gmail.com> 
	 * @return string
	 */
	abstract public function getPersistentKey();

	/**
	 * elements 
	 * 
	 * @var array
	 * @access private
	 */
	private $elements = array();

	/**
	 * getAllElements
	 * 
	 * @access public
	 * @author Pablo López Torres <pablolopeztorres@gmail.com> 
	 * @return void
	 */
	public function getAllElements()
	{
		return $this->elements;
	}

	public function addElement(PhpElement $element)
	{
		$this->elements[$element->getIdentifier()] = $element;
	}

}


class UnableToRetrieveSourcecodeException
{
}

class ProjectNotSetForClassException extends Exception
{
}
